/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package ru.niir.goodfil.ui;

import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.Logger;
import ru.niir.goodfil.db.Good;
import ru.niir.goodfil.db.Order;
import ru.niir.goodfil.db.OrderItem;
import ru.niir.goodfil.db.dic.ClientState;
import ru.niir.goodfil.db.dic.DeliveryType;
import ru.niir.goodfil.db.dic.FailureCause;
import ru.niir.goodfil.db.dic.OrderState;
import ru.niir.goodfil.exceptions.GoodfilSecurityException;
import ru.niir.goodfil.exceptions.ValidationException;
import ru.niir.goodfil.ui.models.OrderItemsSumModel;
import ru.niir.goodfil.utils.Pair;
import ru.niir.goodfil.utils.SumFormat;

import javax.faces.model.SelectItem;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Бин для работы со страницей заказов
 */
public class StorekeeperOrdersBean extends PageBean {
    private static Logger logger = Logger.getLogger(OrdersBean.class);

    private static final String STOREKEEPER_PAGE = "sk2";

    private static final String STOREKEEPER_BEAN_NAME = "StorekeeperOrderBean";

    private static final int SORT_DEFAULT_MAX = 1000;

    int days = gf().getIntOrCreateIfNotExists("storekeeping.days", 3, "Количество дней, за которое будут выводиться заказы на странице кладовщика");


    /**
     * Заказы на выдачу
     */
    private List<Order> ordersFromOutPool;

    /**
     * Заказы на сборку
     */
    private List<Order> ordersFromBuildPool;

    private List<OrderItemsSumModel> orderItemsSum = new ArrayList<OrderItemsSumModel>();

    private ArrayList<Long> orderIds = new ArrayList<Long>();

    private long orderId;

    private int deliveryType = 1;

    private long mainOrderId;

    /**
     * Заказы на выдачу
     */
    public List<Order> getOrdersFromOutPool() {
        StorekeeperOrderBean bean = (StorekeeperOrderBean) getBean(STOREKEEPER_BEAN_NAME);
        bean.release();
        if (this.ordersFromOutPool == null) {

            this.ordersFromOutPool = new ArrayList<Order>();
            List<Order> orders = gf().getOrdersForOut(days);
            for (Order order : orders) {
                order.setClient(gf().getClientById(order.getClientId()));
                order.setManager(gf().getUserById(order.getManagerId()));
                order.setStorekeeper(gf().getUserById(order.getStorekeeperId()));
                gf().addOrderInfo(order);

                this.ordersFromOutPool.add(order);
            }
        }
        return this.ordersFromOutPool;
    }

    /**
     * Заказы на сборку
     */
    public List<Order> getOrdersFromBuildPool() {
        StorekeeperOrderBean bean = (StorekeeperOrderBean) getBean(STOREKEEPER_BEAN_NAME);
        bean.release();
        if (this.ordersFromBuildPool == null) {
            this.ordersFromBuildPool = new ArrayList<Order>();
            List<Order> orders = gf().getOrdersForBuild(days);
            for (Order order : orders) {
                order.setClient(gf().getClientById(order.getClientId()));
                order.setManager(gf().getUserById(order.getManagerId()));
                order.setDeliveryInfoExt(gf().getClientsDeliveryInfo().getOrderDeliveryInfoById(order.getId()));
                gf().addOrderInfo(order);

                if(getDeliveryType() == 5){
                    if(order.getClient().isClientSateIsESHOPDAYTODAY()) this.ordersFromBuildPool.add(order);
                }
                if(getDeliveryType() == 4){
                    if(order.getClient().isClientSateIsTD()) this.ordersFromBuildPool.add(order);
                }

                if(getDeliveryType() == 3){
                    if(order.getClient().getClientStateId() == ClientState.EXPRESS_DELIVERY){
                        this.ordersFromBuildPool.add(order);
                    }
                }

                else if(!order.getClient().isClientSateIsTD() && !order.getClient().isClientSateIsESHOPDAYTODAY() && (getDeliveryType() == DeliveryType.SELF_DELIVERY && !order.getClient().isClientStateIsEXPRESSDELIVERY())){
                    if(order.getDeliveryTypeId() == DeliveryType.SELF_DELIVERY){
                        this.ordersFromBuildPool.add(order);
                    }
                }

                else if(getDeliveryType() == DeliveryType.COMPANY){
                    if(!order.getClient().isClientSateIsESHOPDAYTODAY() && !order.getClient().isClientSateIsTD() && !order.getClient().isClientStateIsEXPRESSDELIVERY() && (order.getDeliveryTypeId() != DeliveryType.SELF_DELIVERY )){
                        this.ordersFromBuildPool.add(order);
                    }
                }
            }
//            Collections.reverse(this.ordersFromBuildPool);

            Collections.sort(this.ordersFromBuildPool, new Comparator<Order>() {
                public int compare(Order o1, Order o2) {
                    Integer i = o1.getSequence()==null ? SORT_DEFAULT_MAX : Integer.parseInt(o1.getSequence());
                    Integer j = o2.getSequence()==null ? SORT_DEFAULT_MAX : Integer.parseInt(o2.getSequence());
                    if(i > j) return 1;
                    else if (i < j) return -1;
                    else return 0;
                }
            });
        }
        return this.ordersFromBuildPool;
    }

    public void refresh() {
        this.ordersFromOutPool = null;
        this.ordersFromBuildPool = null;
        orderIds.clear();
        orderItemsSum.clear();
        orderId = 0;
    }

    private long storekeepOrder_orderId;

    public void storekeepOrder() {
        long orderId = storekeepOrder_orderId;

        StorekeeperOrderBean bean = (StorekeeperOrderBean) getBean(StorekeeperOrderBean.BEAN_NAME);
        bean.initialize(orderId);

        sendRedirect(STOREKEEPER_PAGE);
    }

    public void updateOrdersForDefaultSorting(){
        for(Order order : ordersFromBuildPool){
            order.setSequence("");
            order.setDeliveryInfoExt(gf().getClientsDeliveryInfo().getOrderDeliveryInfoById(order.getId()));
            try {
                if(gf().getOrderById(order.getId()).getOrderStateIsOutput()){
                    gf().updateOrder(order);
                }
            } catch (ValidationException e) {
                logger.error(e.getMessage());
            }
        }
    }

    public List<OrderItemsSumModel> getOrderItemsSum() {
        if(orderIds.size() == 0) return new ArrayList<OrderItemsSumModel>();
        List<OrderItem> orderItems = gf().getOrderItemsSumByOrderIds(orderIds);
        for(OrderItem item : orderItems){
            Good good = gf().getGoodById(item.getGoodId());
            OrderItemsSumModel model = new OrderItemsSumModel();
            model.setGoodCode(good.getCode());
            model.setGoodCount(item.getCount());
            model.setFreeGoodCount(good.getCount());
            orderItemsSum.add(model);
        }
        Collections.sort(orderItemsSum, new Comparator<OrderItemsSumModel>() {
            public int compare(OrderItemsSumModel o1, OrderItemsSumModel o2) {
                return o1.getGoodCode().compareTo(o2.getGoodCode());
            }
        });

        for (long orderId : orderIds){
            gf().setOrderState_Unsafe(orderId, OrderState.ACCEPTED_BY_STORAGE);
        }
        return orderItemsSum;
    }

    public long getStorekeepOrder_orderId() {
        return storekeepOrder_orderId;
    }

    public void setStorekeepOrder_orderId(long storekeepOrder_orderId) {
        this.storekeepOrder_orderId = storekeepOrder_orderId;
    }

    public long getOrderId() {
        return orderId;
    }

    public void setOrderId(long orderId) {
        this.orderId = orderId;
    }

    public void addOrderId(){
        for (long l : orderIds){
            if(getOrderId() == l){
                orderIds.remove(l);
                return;
            }
        }
        orderIds.add(getOrderId());
    }

    public List<SelectItem> getFailureCauseList(){
        List<SelectItem> list = new ArrayList<SelectItem>();
        list.add(new SelectItem(-1, "Не выбрано"));
        for (Pair pair : FailureCause.list()) {
            list.add(new SelectItem(pair.getId(), pair.getValue()));
        }
        return list;
    }

    public void save(){
        for(Order order : ordersFromBuildPool){
            //order.setDeliveryInfoExt(gf().getClientsDeliveryInfo().getOrderDeliveryInfoById(order.getId()));
            try {
                int orderState = gf().getOrderById(order.getId()).getOrderStateId();
                if(orderState == OrderState.OUTPUT || orderState == OrderState.ACCEPTED_BY_STORAGE){
                    gf().updateOrder(order);
                }
            } catch (ValidationException e) {
                logger.error("ValidationException: " + e.getMessage());
            }
        }
    }


    public StorekeeperOrdersBean() {
        //  Доступ на страницу заказов разрешен только администраторам, кладовщикам и менеджерам
        if (!(getSecurityBean().getIsRoleAdministrator() ||
                getSecurityBean().getIsRoleManager() ||
                getSecurityBean().getIsRoleStoreman()|| getSecurityBean().getIsRoleKassa() )) {
            throw new GoodfilSecurityException("Доступ на страницу заказов разрешен только администраторам, менеджерам, работникам бухгалтерии и кладовщикам");
        }
        init();
    }

    public List<SelectItem> getDeliveryTypes(){
        List<SelectItem> list = new ArrayList<SelectItem>();
        for(Pair pair : DeliveryType.list()){
            if(pair.getId() == DeliveryType.DOCUMENS_EXECUTION || pair.getId() == DeliveryType.TRANSPORT_COMPANY_RETURN) continue;
            list.add(new SelectItem(pair.getId(), pair.getValue()));
        }
        list.add(new SelectItem(3, "Экспресс-доставка"));
        list.add(new SelectItem(4, "Торговые дома"));
        list.add(new SelectItem(5, "Интернет-магазин день в день"));
        return list;
    }

    public int getDeliveryType() {
        return deliveryType;
    }

    public void setDeliveryType(int deliveryType) {
        this.deliveryType = deliveryType;
    }

    public String getDeliveryTypeAsString(){
        if(getDeliveryType() == 3) return "Экспресс-доставка";
        if(getDeliveryType() == 4) return "Торговые дома";
        if(getDeliveryType() == 5) return "Интернет-магазин день в день";
        return DeliveryType.asString(getDeliveryType());
    }

    public String getOrdersForBuildSum(){
        double sum = 0;
        for(Order order : ordersFromBuildPool){
            sum += order.getSum();
        }
        return SumFormat.formatSum("###,###,##0.00", sum);
    }

    public String getOrdersForOutSum(){
        double sum = 0;
        for(Order order : ordersFromOutPool){
            sum += order.getFactSum();
        }
        return SumFormat.formatSum("###,###,##0.00", sum);
    }

    public long getMainOrderId() {
        return mainOrderId;
    }

    public void setMainOrderId(long mainOrderId) {
        this.mainOrderId = mainOrderId;
    }

    public boolean getIsCanCommitOrders(){
        int canCommit = gf().getIntOrCreateIfNotExists("can.storage.confirm.orders", 0, "Можно подтверждать заказы");
        return canCommit == 1;
    }

}
